import React from 'react';
import {
  FlatList,
  StyleSheet,
  Text,
  View,
  TextInput,
  Dimensions,
  Platform,
} from 'react-native';
import {bindActionCreators} from 'redux';
import * as messageActionCreator from '../../actions/message-actions';
import {connect} from 'react-redux';
import {connectActionSheet} from '@expo/react-native-action-sheet';
import {getRealSize, RequestCameraPermission, Touchable} from '../../utils';
import IconFont from '../../resource/iconfont';
import _ from 'lodash';
import ThemeStyles from '../../styles';
import StateMessage from './state-message';
import ImageMessage from './image-message';
import TextMessage from './text-message';
import Separator from '../../components/separator';
import Toast from '../../components/toast';
import * as RNImagePicker from 'react-native-image-picker';
import RNFS from 'react-native-fs';
import config from '../../../config.json';
import {UploadState} from '../../components/file-upload';
import ImageZoomModal from '../../components/image-zoom-modal';
import {I18n} from '../../reducers/intl';
import Spinner from '../../components/spinner';

const MessageType = {
  State: 'state',
  Text: 'text',
  Image: 'image',
};

class ChatScreen extends React.Component {
  static navigationOptions = () => ({
    headerBackTitleStyle: Platform.OS === 'ios' && {
      height: 0,
      width: 0,
    },
    title: I18n.t('page.title.chat'),
  });

  state = {
    inputValue: '',
    imageModalVisible: false,
    images: [],
    uploading: false,
    percentage: 0,
  };
  componentDidMount() {
    const {navigation, messageActions} = this.props;
    const conversation = navigation.getParam('item');
    messageActions.setConversation(conversation);
    messageActions.readMessage(conversation.id);
  }

  renderMessage = ({item}) => {
    const {conversation, user} = this.props;
    const message = {...item};
    if (item.type === MessageType.State) {
      message.type = MessageType.State;
      return (
        <StateMessage
          title={conversation.order_no}
          date={message.created}
          state={message.message}
        />
      );
    }
    const sender = conversation[message.type];
    message.self = sender.id === user.id;
    message.name = sender.clinic_name || sender.vendor_name || sender.email;
    message.avatar = _.get(sender, 'avatar.url', '');
    if (_.startsWith(message.message, '<img')) {
      message.type = MessageType.Image;
      const url = message.message.substring(10, message.message.length - 33);
      // console.log('message', message.message);
      return (
        <ImageMessage
          date={message.created}
          url={url}
          self={message.self}
          avatar={message.avatar}
          name={message.name}
          rate={item.rate}
          state={item.state}
          onView={() => {
            this.setState(
              {
                images: [{url}],
              },
              () => this.setState({imageModalVisible: true}),
            );
          }}
        />
      );
    }
    return (
      <TextMessage
        date={message.created}
        content={message.message}
        self={message.self}
        avatar={message.avatar}
        name={message.name}
      />
    );
  };

  onSend = async () => {
    const {conversation, messageActions} = this.props;
    const payload = _.trim(this.state.inputValue);
    if (!payload) {
      return;
    }
    this.setState({inputValue: ''});
    try {
      await messageActions.sendMessage(conversation.id, {
        content: this.state.inputValue,
      });
      this.chatList.scrollToEnd();
    } catch (e) {
      Toast.show(e.message);
    }
  };

  scrollToBottom = () => {
    setTimeout(() => {
      this.chatList &&
        this.chatList.scrollToEnd({
          animated: false,
        });
    }, 500);
  };

  onPickImage = () => {
    const {imageOptions} = this.props;
    this.props.showActionSheetWithOptions(
      {
        options: imageOptions,
        cancelButtonIndex: 2,
        destructiveButtonIndex: 2,
        textStyle: {flex: 1},
      },
      index => this.onShowPick(index),
    );
  };

  onShowPick = async index => {
    const upload = this.upload;
    if (index === 0) {
      try {
        await RequestCameraPermission();
      } catch (e) {
        return Toast.show(e.message);
      }
      RNImagePicker.launchCamera(
        {
          mediaType: 'photo',
          includeBase64: false,
          maxHeight: Dimensions.get('screen').height,
          maxWidth: Dimensions.get('screen').width,
        },
        upload,
      );
    } else if (index === 1) {
      RNImagePicker.launchImageLibrary(
        {
          mediaType: 'photo',
          includeBase64: false,
          maxHeight: Dimensions.get('screen').height,
          maxWidth: Dimensions.get('screen').width,
        },
        upload,
      );
    }
  };

  upload = response => {
    const {token, conversation, messageActions} = this.props;
    // const url = `${config.httpClient.host}/web/planimage/new`;
    const url = `${config.httpClient.host}/web/image/new`;
    if (response.didCancel) {
      return;
    }
    // {
    //   "fileName": "rn_image_picker_lib_temp_d25c7647-f2a5-48a0-9582-8c0690347bc6.jpg",
    //     "fileSize": 93393,
    //     "height": 293,
    //     "type": "image/jpeg",
    //     "uri": "file:///data/user/0/com.molarapp/cache/rn_image_picker_lib_temp_d25c7647-f2a5-48a0-9582-8c0690347bc6.jpg",
    //     "width": 392
    // }
    const uploadFile = {
      state: UploadState.PENDING,
      name: 'file',
      filename: response.name,
      filepath: Platform.select({
        android: response.uri.replace('file://', ''),
        ios: response.uri.replace('file://', ''),
      }),
      filetype: response.type,
    };
    console.log(url, token.access, uploadFile);
    const {promise} = RNFS.uploadFiles({
      toUrl: url,
      files: [uploadFile],
      fields: {file: 'file'},
      binaryStreamOnly: false,
      method: 'POST',
      headers: {
        Authorization: `Bearer ${token.access}`,
      },
      beginCallback: async response => {
        // await messageActions.appendMessage(conversation.id, {
        //   jobId: response.jobId,
        //   state: UploadState.PENDING,
        //   message: '<img src="" class="message-content-image"/>',
        // });
        this.setState({
          uploading: true,
          percentage: 0,
        });
        this.scrollToBottom();
      },
      progressCallback: async response => {
        let percentage = Math.floor(
          (response.totalBytesSent / response.totalBytesExpectedToSend) * 100,
        );
        // console.log('percentage', percentage);
        if (percentage % 10 === 0) {
          this.setState({
            percentage,
          });
          // await messageActions.updateMessageImageProgress(
          //   conversation.id,
          //   response.jobId,
          //   percentage,
          // );
          this.scrollToBottom();
        }
      },
    });
    promise
      .then(response => {
        //HTTP response响应
        if (response.statusCode == 200) {
          console.log('FILES UPLOADED!'); // response.statusCode状态码, response.headers响应header, response.body 响应body
          const payload = JSON.parse(response.body);
          messageActions.updateMessageImageSuccess(
            conversation.id,
            response.jobId,
            _.get(payload, 'data.url'),
          );
          this.scrollToBottom();
        } else {
          console.log('SERVER ERROR');
        }
      })
      .catch(err => {
        //HTTP请求异常
        if (err.description === 'cancelled') {
          // cancelled by user
        }
        console.log(err);
      })
      .finally(() =>
        this.setState({
          uploading: false,
          percentage: 100,
        }),
      );
  };

  render() {
    const {conversation} = this.props;
    const messages = _.get(conversation, 'messages', []);
    // console.log('render', this.state.images);
    // console.log('conversation', JSON.stringify(conversation));
    return (
      <View style={Styles.container}>
        <Spinner
          visible={this.state.uploading}
          textContent={`${this.state.percentage} %`}
        />
        <FlatList
          ref={ref => {
            this.chatList = ref;
          }}
          onContentSizeChange={(contentWidth, contentHeight) =>
            this.scrollToBottom({contentWidth, contentHeight})
          }
          style={Styles.list}
          data={_.orderBy(messages, 'created', 'asc')}
          keyExtractor={item => item.uid || item.id}
          ItemSeparatorComponent={() => <Separator />}
          renderItem={this.renderMessage}
        />
        <View style={Styles.inputBar}>
          <Touchable onPress={this.onPickImage}>
            <View style={Styles.img}>
              <IconFont name="molarimg" size={getRealSize(32)} color="#999" />
            </View>
          </Touchable>
          <View style={Styles.input}>
            <TextInput
              style={Styles.textInput}
              onBlur={this.scrollToBottom}
              onFocus={this.scrollToBottom}
              onChangeText={text => this.setState({inputValue: text})}
              value={this.state.inputValue}
            />
          </View>
          <Touchable onPress={this.onSend}>
            <View style={Styles.btn}>
              <Text style={Styles.btnLabel}>{I18n.t('button.send')}</Text>
            </View>
          </Touchable>
        </View>
        <ImageZoomModal
          visible={this.state.imageModalVisible}
          images={this.state.images}
          onClose={() => this.setState({imageModalVisible: false})}
        />
      </View>
    );
  }
}

const mapStateToProps = state => ({
  appState: state.appState,
  user: state.user,
  token: state.token,
  conversation: state.conversation,
  imageOptions: [
    I18n.t('options.image.camera'),
    I18n.t('options.image.album'),
    I18n.t('options.image.close'),
  ],
});

const mapDispatchToProps = dispatch => ({
  messageActions: bindActionCreators(messageActionCreator, dispatch),
});

export default connect(
  mapStateToProps,
  mapDispatchToProps,
)(connectActionSheet(ChatScreen));

const Styles = StyleSheet.create({
  container: {
    flex: 1,
    alignItems: 'center',
  },
  list: {
    flex: 1,
    width: Dimensions.get('screen').width,
    backgroundColor: '#f7f7f7',
  },
  inputBar: {
    flexDirection: 'row',
    backgroundColor: 'white',
    paddingVertical: getRealSize(4),
    paddingHorizontal: getRealSize(12),
  },
  img: {
    alignItems: 'center',
    justifyContent: 'center',
  },
  input: {
    flex: 1,
    marginHorizontal: getRealSize(8),
    paddingHorizontal: getRealSize(8),
    borderRadius: getRealSize(4),
    borderWidth: getRealSize(1),
    borderColor: '#e8e8e8',
    backgroundColor: '#f6f6f6',
  },
  textInput: {
    padding: 0,
    flex: 1,
  },
  btn: {
    justifyContent: 'center',
    alignItems: 'center',
    backgroundColor: ThemeStyles.Color.primary.color,
    paddingHorizontal: getRealSize(12),
    paddingVertical: getRealSize(4),
    borderRadius: getRealSize(4),
    height: getRealSize(32),
    width: getRealSize(65),
  },
  btnLabel: {
    fontSize: getRealSize(12),
    fontWeight: 'bold',
    textAlign: 'center',
    width: getRealSize(32),
    color: 'white',
  },
});
